package com.ustc.hewei.nettyrpc2_0.common.codec;

import com.ustc.hewei.nettyrpc2_0.common.enumeration.PackageType;
import com.ustc.hewei.nettyrpc2_0.common.enumeration.RpcError;
import com.ustc.hewei.nettyrpc2_0.common.exception.RpcException;
import com.ustc.hewei.nettyrpc2_0.common.serializer.CommonSerializer;
import com.ustc.hewei.nettyrpc2_0.common.warp.RpcRequest;
import com.ustc.hewei.nettyrpc2_0.common.warp.RpcResponse;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
* @description: netty解码器
* @author hewei
* @date 2022/9/5 20:00
* @version 1.0
*/

public class CommonDecode extends ReplayingDecoder {
    private static final int MAGIC_NUMBER = 0xCAFEBABE;
    private static final Logger logger = LoggerFactory.getLogger(CommonDecode.class);

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int magic = in.readInt();
        if (magic != MAGIC_NUMBER) {
            logger.error("未知的协议包 {}", magic);
            throw new RpcException(RpcError.UNKNOWN_PROTOCOL, "解码时收到未知识别的协议包");
        }
        int packageType = in.readInt();
        Class<?> packageClass;
        if (packageType == PackageType.REQUEST.getCode()) {
            packageClass = RpcRequest.class;
        } else if (packageType == PackageType.RESPONSE.getCode()) {
            packageClass = RpcResponse.class;
        } else {
            logger.error("未知的包的类型 {}", packageType);
            throw new RpcException(RpcError.UNKNOWN_PACKAGE, "解码时收到未知的包的类型");
        }
        int serializerType = in.readInt();
        CommonSerializer serializer = CommonSerializer.getByCode(serializerType);
        if (serializer == null) {
            logger.error("未知的序列化类型 {}", serializerType);
            throw new RpcException(RpcError.UNKNOWN_SERIALIZER, "解码时收到未知的序列化类型");
        }
        int messageLength = in.readInt();
        byte[] data = new byte[messageLength];
        in.readBytes(data);
        out.add(serializer.deSerializer(data, packageClass));
    }
}
